package evolution;

import java.util.LinkedList;

import org.jgap.impl.CompositeGene;

import bangor.aiia.jge.bnf.BNFSymbol;
import bangor.aiia.jge.population.InvalidPhenotypeException;

public class CodonString {

	public int index;
	public int maxWraps;
	public int currentWrap;
	public int[] values;

	public CodonString(int[] values, int maxWraps){
		this.values = values;
		this.maxWraps = maxWraps;
		this.index = -1;
	}
	
	public CodonString(String binary, int size, int maxWraps){
		values = decode(binary, size);
		this.maxWraps = maxWraps;
		this.index = -1;
	}
	
	public CodonString(CompositeGene gene, int maxWraps){
		values = new int[gene.size()];
		for(int i = 0; i < gene.size(); i++){
			values[i] = (Integer)gene.geneAt(i).getAllele();
		}
	}
	public int[] decode(String binary, int size){
		// Calculate the number of codons in the genotype string
		// Note: It is possible the last codon to have less than codonSize bits
		int codonsNum = (int) Math.ceil( (double) binary.length() / (double) size);
		
		// Convert the Binary String (DNA) into an Integers Array (RNA)
		int[] rna = new int[codonsNum];
		for (int i = 0; i < codonsNum; i++) {
			// Calculate the position of the next codon
			int start = i * size;
			int end = (start + size < binary.length())? start + size : binary.length();
			// Convert the binary string value into a decimal integer value and store it
			rna[i] = Integer.parseInt(binary.substring(start, end), 2);			
		}
		return rna;
	}

	
	/**
	 * Calculates and sets the next codon index of the RNA which will be used.
	 * Also, it updates the <code>currentWrap</code> field if necessary.
	 * 
	 * @param list The working linked list with the processed phenotype symbols
	 */
	public void increment() throws InvalidPhenotypeException {
		
		int previousIndex = index;
		
		// Set the index of the codon to be used
		index++;
		
		// Check if a wrap is necessary
		if (index == values.length) {
			index = 0;
			currentWrap++;
		}
		
		// Check if maximum allowed wraps is reached
		if (currentWrap > maxWraps) {
			//createPhenotypeValue(list);
			index = previousIndex;
			throw new InvalidPhenotypeException("Invalid Phenotype: Max Wraps exceeded (" + (currentWrap - 1) + ")");
		}
		
	}
	
	public int currentValue(){
		return values[index];
	}

	public int next()  throws InvalidPhenotypeException{
		increment();
		return currentValue();
	}

}
